package com.naiterui.ehp.bs.doctor.utils;

import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.im4java.core.ConvertCmd;
import org.im4java.core.GMOperation;
import org.im4java.core.IM4JavaException;
import org.im4java.process.Pipe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 处理系统中的文件上传和下载的公共服务类
 * <P>File name : AttchmentHandle.java </P>
 * <P>Author : zhouyanxin </P>
 * <P>Date : 2014-9-28 </P>
 */
@Service
public class AdAttchmentHandle {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdAttchmentHandle.class);

    @Autowired
    private AdAttchmentTypes attchmentType;

    private String path;

    public AdAttchmentHandle() {
        this.path = ConfigUtil.getString("adBaseUpload");
    }

    public String getBasePath() {
        return this.path;
    }

    public String[] upload(Integer[] types, MultipartFile[] files, String... parameters) {

        if (files == null || files.length == 0) {
            return null;
        }

        List<String> paths = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {

            MultipartFile multipartFile = files[i];

            Integer attType = types[i];

            try {

                String uploadPath = this.upload(attType, multipartFile, false, parameters);

                paths.add(uploadPath);

            } catch (Exception e) {

                LOGGER.error("文件复制失败", e);

            }

        }

        return paths.isEmpty() ? null : paths.toArray(new String[paths.size()]);

    }

    /**
     * 上传单个文件
     *
     * @param type          文件类型
     * @param multipartFile 文件
     * @param compress      是否压缩，默认不压缩
     * @param parameters
     *
     * @return
     *
     * @throws BusinessException
     */
    public String upload(Integer type, MultipartFile multipartFile, boolean compress, String... parameters) throws BusinessException {
        return this.upload(type, multipartFile, compress, true, parameters);
    }

    /**
     * 上传单个文件
     *
     * @param type          文件类型
     * @param multipartFile 文件
     * @param compress      是否压缩，默认不压缩
     * @param async         是否异步（默认:true）
     * @param parameters
     *
     * @return
     *
     * @throws BusinessException
     */
    public String upload(Integer type, MultipartFile multipartFile, boolean compress, boolean async, String... parameters) throws BusinessException {
        if (type == null || multipartFile == null) {
            return null;
        }

        String url = this.attchmentType.getAttURI(type, parameters);

        String finalName = UUID.randomUUID() + ".jpg";

        String dirFile = this.path + url;

        try {

            InputStream inputStream = multipartFile.getInputStream();

            // 压缩图片
            if (compress) {

                this.compress(inputStream, dirFile, finalName, async);

            } else {

                File file = new File(dirFile, finalName);

                FileUtils.copyInputStreamToFile(inputStream, file);

            }

        } catch (Exception e) {

            LOGGER.warn("文件压缩失败", e);

            throw new BusinessException(ExceptionCodes.FILE_UPLOAD_LOST, e);

        }
        return url + finalName;
    }

    /**
     * 删除文件
     *
     * @param filePath 文件相对路径
     */
    public void remove(String filePath) {

        if (StringUtils.isNotEmpty(filePath)) {

            try {

                File file = new File(this.path + "" + filePath);

                boolean delete = file.delete();

                LOGGER.debug("删除文件路径：{} 删除状态：{}", filePath, delete);

            } catch (Exception e) {

                LOGGER.error("文件删除发生异常，filePath:{}", filePath, e);

            }

        }

    }


    /**
     * 根据输入流压缩图片，
     *
     * @param inputStream 输入流
     * @param targetPath  图片保存目标路径
     * @param asyncMode   是否异步
     */
    private void compress(InputStream inputStream, String targetPath, String fileName, boolean asyncMode) throws InterruptedException, IOException,
            IM4JavaException {

        LOGGER.info("压缩文件 路径：{} 文件名：{}", targetPath, fileName);

        // 输入流不能为nul
        assert inputStream != null;

        // 目标路径,文件名不能为null
        if (StringUtils.isAnyEmpty(targetPath, fileName)) {
            throw new RuntimeException("targetPath和fileName不能为null targetPath:" + targetPath + " fileName:" + fileName);
        }

        File file = new File(targetPath);
        if (!file.exists()) {

            // 如果路径不存在,则创建
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("文件目录创建失败" + targetPath);
            }

        }

        Pipe pipeIn = new Pipe(inputStream, null);

        GMOperation operation = new GMOperation();

        operation.addImage("-");

        operation.addRawArgs("-resize", "640x480>");

        operation.quality(80D);

        operation.addImage(targetPath + fileName);

        ConvertCmd convertCmd = new ConvertCmd(true);

        convertCmd.setInputProvider(pipeIn);

        convertCmd.setAsyncMode(asyncMode);

        convertCmd.run(operation);

    }

}
